/**
 * gpio_operations.c
 * 
 * 使用Linux标准文件操作接口实现GPIO操作
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>

// GPIO相关路径定义
#define GPIO_EXPORT_PATH "/sys/class/gpio/export"
#define GPIO_UNEXPORT_PATH "/sys/class/gpio/unexport"
#define GPIO_DIRECTION_PATH_FORMAT "/sys/class/gpio/gpio%d/direction"
#define GPIO_VALUE_PATH_FORMAT "/sys/class/gpio/gpio%d/value"

/**
 * gpio_export - 导出GPIO引脚
 * @gpio: GPIO引脚编号
 * 
 * 返回值: 成功返回0，失败返回-1
 */
int gpio_export(int gpio)
{
    int fd;
    char buf[64];
    
    // 打开export文件
    fd = open(GPIO_EXPORT_PATH, O_WRONLY);
    if (fd < 0) {
        perror("Failed to open GPIO export file");
        return -1;
    }
    
    // 写入GPIO编号
    sprintf(buf, "%d", gpio);
    if (write(fd, buf, strlen(buf)) < 0) {
        perror("Failed to export GPIO");
        close(fd);
        return -1;
    }
    
    close(fd);
    return 0;
}

/**
 * gpio_unexport - 取消导出GPIO引脚
 * @gpio: GPIO引脚编号
 * 
 * 返回值: 成功返回0，失败返回-1
 */
int gpio_unexport(int gpio)
{
    int fd;
    char buf[64];
    
    // 打开unexport文件
    fd = open(GPIO_UNEXPORT_PATH, O_WRONLY);
    if (fd < 0) {
        perror("Failed to open GPIO unexport file");
        return -1;
    }
    
    // 写入GPIO编号
    sprintf(buf, "%d", gpio);
    if (write(fd, buf, strlen(buf)) < 0) {
        perror("Failed to unexport GPIO");
        close(fd);
        return -1;
    }
    
    close(fd);
    return 0;
}

/**
 * gpio_set_direction - 设置GPIO方向
 * @gpio: GPIO引脚编号
 * @direction: 方向（"in"或"out"）
 * 
 * 返回值: 成功返回0，失败返回-1
 */
int gpio_set_direction(int gpio, const char *direction)
{
    int fd;
    char buf[64];
    
    // 构建direction文件路径
    sprintf(buf, GPIO_DIRECTION_PATH_FORMAT, gpio);
    
    // 打开direction文件
    fd = open(buf, O_WRONLY);
    if (fd < 0) {
        perror("Failed to open GPIO direction file");
        return -1;
    }
    
    // 写入方向
    if (write(fd, direction, strlen(direction)) < 0) {
        perror("Failed to set GPIO direction");
        close(fd);
        return -1;
    }
    
    close(fd);
    return 0;
}

/**
 * gpio_set_value - 设置GPIO输出值
 * @gpio: GPIO引脚编号
 * @value: 输出值（0或1）
 * 
 * 返回值: 成功返回0，失败返回-1
 */
int gpio_set_value(int gpio, int value)
{
    int fd;
    char buf[64];
    
    // 构建value文件路径
    sprintf(buf, GPIO_VALUE_PATH_FORMAT, gpio);
    
    // 打开value文件
    fd = open(buf, O_WRONLY);
    if (fd < 0) {
        perror("Failed to open GPIO value file");
        return -1;
    }
    
    // 写入值
    if (write(fd, value ? "1" : "0", 1) < 0) {
        perror("Failed to set GPIO value");
        close(fd);
        return -1;
    }
    
    close(fd);
    return 0;
}

/**
 * gpio_get_value - 读取GPIO输入值
 * @gpio: GPIO引脚编号
 * @value: 存储读取值的指针
 * 
 * 返回值: 成功返回0，失败返回-1
 */
int gpio_get_value(int gpio, int *value)
{
    int fd;
    char buf[64];
    char ch;
    
    // 构建value文件路径
    sprintf(buf, GPIO_VALUE_PATH_FORMAT, gpio);
    
    // 打开value文件
    fd = open(buf, O_RDONLY);
    if (fd < 0) {
        perror("Failed to open GPIO value file");
        return -1;
    }
    
    // 读取值
    if (read(fd, &ch, 1) < 0) {
        perror("Failed to read GPIO value");
        close(fd);
        return -1;
    }
    
    // 解析值
    *value = (ch == '1') ? 1 : 0;
    
    close(fd);
    return 0;
}

/**
 * gpio_init - 初始化GPIO引脚
 * @gpio: GPIO引脚编号
 * @direction: 方向（"in"或"out"）
 * 
 * 返回值: 成功返回0，失败返回-1
 */
int gpio_init(int gpio, const char *direction)
{
    // 导出GPIO
    if (gpio_export(gpio) < 0) {
        // 如果已经导出，则继续执行
        if (errno != EBUSY) {
            return -1;
        }
    }
    
    // 设置方向
    if (gpio_set_direction(gpio, direction) < 0) {
        return -1;
    }
    
    return 0;
}

/**
 * gpio_cleanup - 清理GPIO资源
 * @gpio: GPIO引脚编号
 * 
 * 返回值: 成功返回0，失败返回-1
 */
int gpio_cleanup(int gpio)
{
    return gpio_unexport(gpio);
}